package yz_service

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"peilian-api/app/global/common"
	"peilian-api/app/global/databases/redisop"
	"peilian-api/app/global/variable"
	"peilian-api/utils/tools"
	"time"

	"github.com/gin-gonic/gin"
)

type YzApi struct{}

// 获取接口凭证 access_token
func getAccessTokenApi(ctx *gin.Context, isRefresh bool) (string, error) {
	var refresh = variable.Config.Yz.Refresh
	if isRefresh {
		refresh = "true"
	}
	data := map[string]interface{}{
		"client_id":      variable.Config.Yz.ClientId,      // 开发者应用ID
		"client_secret":  variable.Config.Yz.ClientSecret,  // 开发者应用secret
		"authorize_type": variable.Config.Yz.AuthorizeType, // 固定的授权方式 silent
		"grant_id":       variable.Config.Yz.GrantId,       // 授权店铺id
		"refresh":        refresh,                          // 是否刷新
	}
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		variable.Config.Yz.TokenUrl,
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		return "", err
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBodyCtx(ctx, resp, &res)
	if err != nil {
		return "", err
	}
	if code, _ := res["code"].(float64); code != 200 {
		return "", fmt.Errorf("接口请求错误")
	}
	b, _ := json.Marshal(res["data"])
	return string(b), nil
}

// 单项解密接口
func (*YzApi) DecryptSingle(ctx *gin.Context, source string, accessToken string) (string, error) {
	data := map[string]interface{}{
		"source": source,
	}
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		fmt.Sprintf("%s?access_token=%s", variable.Config.Yz.SecretDecryptSingle, accessToken),
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		return "", err
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBodyCtx(ctx, resp, &res)
	if err != nil {
		return "", err
	}
	if code, _ := res["code"].(float64); code != 200 {
		return "", fmt.Errorf("接口请求错误")
	}
	return res["data"].(string), nil
}

// 分页查询微商城销售中和已售罄商品列表
func (ya *YzApi) YzItemsSearch(ctx *gin.Context, accessToken string) (interface{}, error) {
	data := map[string]interface{}{
		"page_no":   1,
		"page_suze": 20,
	}
	reqJsonData, _ := json.Marshal(data)
	resp, err := http.Post(
		fmt.Sprintf("%s?access_token=%s", variable.Config.Yz.ItemSearch, accessToken),
		"application/json",
		bytes.NewReader(reqJsonData),
	)
	if err != nil {
		return "", err
	}
	if resp != nil {
		defer resp.Body.Close()
	}

	res := make(map[string]interface{})
	err = tools.ReadResponseBodyCtx(ctx, resp, &res)
	if err != nil {
		return "", err
	}
	if code, _ := res["code"].(float64); code != 200 {
		return "", fmt.Errorf("接口请求错误")
	}
	return res["data"], nil
}

// 重新生成token
func (ya *YzApi) RetryGenerateAccessTokenApi(ctx *gin.Context) (string, error) {

	err := redisop.DelKey(ctx, fmt.Sprintf(common.RedisYzTokenKey, variable.Config.Yz.GrantId))
	if err != nil {
		return "", err
	}
	token, err := ya.GetAccessTokenApi(ctx)
	if err != nil {
		return "", err
	}
	return token, nil
}

// 维护token是否过期
func (*YzApi) GetAccessTokenApi(ctx *gin.Context) (string, error) {
	// 先从redis获取token 重试多次
	var tokenInfo TokenInfo
	token, err := redisop.GetStr(ctx, fmt.Sprintf(common.RedisYzTokenKey, variable.Config.Yz.GrantId))
	if err != nil {
		return "", err
	}
	if token == "" {
		token, err = getAccessTokenApi(ctx, true)
		if err != nil {
			return "", err
		}
		err := json.Unmarshal([]byte(token), &tokenInfo)
		if err != nil {
			return "", err
		}
		// 获取当前时间的时间戳
		milli := time.Now().UnixMilli()
		err = redisop.SetStr(ctx, fmt.Sprintf(common.RedisYzTokenKey, variable.Config.Yz.GrantId), token, time.Duration(tokenInfo.Expires-milli)*time.Millisecond-100000)
		if err != nil {
			return "", err
		}
		return tokenInfo.AccessToken, nil
	}
	err = json.Unmarshal([]byte(token), &tokenInfo)
	if err != nil {
		return "", err
	}

	return tokenInfo.AccessToken, nil
}
